/**
 * Flexis JS Framework
 * A simple web application framework for modular programming.
 * @author Sam Vervaeck
 * @version 0.1.2
 * @see http://vervaeck.homenet.org/projects/flexis-js
 */

/**
 * Publicly available buffers
 */
var init;

/**
 * Application constructor using a specific configuration
 * @class Provides information about the current initialized applications.
 * @param {String|Object} specs Application specification; can be a JSON file or a configuration object.
 * @property {jQuery[]} Forms 
 * @property {Object[]} Objects
 */
function Application (specs) {
	
	var self = this;
	this.forms = [];
	this.objects = [];
	
	/**
	 * Load a certain user interface into the application.
	 * @param {Object|String} form The specification of the form
	 */
	this.forms.Add = function (form) {
		
		var properties = $.extend (true, self.form, typeof form == "string" ? { name: form } : form);
		
		$(function () { // make sure we can manipulate the document
		
			var content = $("<div></div>").load (self.path + properties.name + ".html", function () {
				
				$(self.container).append (this);
				
				$.getScript (self.path + properties.name + ".js", function () {
					if (init.call (self, properties)) {
						console.log ("Form scripts for <" + properties.name + "> setup successfully");
					} else {
						console.log ("Could not setup <" + properties.name + "> for <" + self.name + ">");
					}
				});
				
				console.log ("Form <" + properties.name + "> for application <" + self.name + "> loaded");
				self.forms.push (content);
			});
		});
	}
	
	/**
	 * Load a certain object into the application.
	 * @param {Object|String} object The specification of the object
	 */
	this.objects.Add = function (object) {
		
		var properties = $.extened (true, self.object, typeof object == "string" ? { name: object } : object);
	
		$.getScript (self.path + properties.name + ".js", function () {
			console.log ("Loaded program application <" + properties.name + "> for application <" +  self.name + ">");
		});
	}
	
	// Variable declarations
	self.name = specs.name;
	self.location = specs.location;
	self.path = self.location + "/" + self.name + "/";
	self.container = specs.container;
	
	// Application.BeforeLoad.Trigger (self);
	
	// Load application configuration
	$.getJSON (self.path + "app.json", function (properties) {
	
		if (properties) {
		
			$.each (properties, function (key, property) {
				if (! self[key]) {
					self[key] = property;
				}
			});			
			
			if (properties.forms) {
				$.each (properties.forms, function (index, form) {
					self.forms.Add (form);
				});
			}
			
			if (properties.objects) {
				$.each (properties.objects, function (index, object) {
					self.objects.Add (object);
				});
			}
			
			Application.instances.push (self);
			// Application.Success.trigger (self);
			window[properties.namespace] = self;
		
		} else {
			
			// Application.Fail.trigger (self);
			throw "Failed to load application <" + self.name + "> from " + self.path;
		
		}
	});
}

/**
 * Collection of applications that are running.
 * @static
 */
Application.instances = [];

/**
 * Load all the applications using a configuration object
 * @param {Object[]|String[]} configs An array of configuration objects to load.
 * @param {Object} defaults The default configuration values.
 */
Application.Load = function (specs, defaults) {
	$.each (specs, function (index, spec) {
		var config = $.extend (true, defaults, typeof spec == "string" ? { name: spec } : spec);
		if (config.enabled) {
			try {
				new Application (config);
			} catch (e) {
				console.log (e);
			}
		} else {
			console.log ("Application " + config.name + " skipped (disabled)");
		}
	});
}